#include <iostream>
#include <cstring>
#include <mysql/mysql.h>

#define HOST "127.0.0.1" // mysql一般只允许本地ip访问
#define USER "root"
#define PASS "wanglong050528"
#define DBNAME "gobang"
#define PORT 3306

int main()
{
    // 1. 初始化 mysql 句柄
    MYSQL *mysql = mysql_init(NULL); // 传空会自己在堆上申请空间来初始化句柄并返回首地址
    if (mysql == NULL)
    {
        std::cout << "mysql init failed" << std::endl;
        return -1;
    }

    // 2. 连接服务器
    // MYSQL* mysql_real_connect(mysql,host,user,password,dbname,port,unix_socket,flag)
    if (mysql_real_connect(mysql, HOST, USER, PASS, DBNAME, PORT, NULL, 0) == NULL)
    {
        // mysql_real_connect返回值为空表示连接失败
        // mysql_errno函数可以查看失败原因
        std::cout << "connect mysql server failed: " << mysql_errno(mysql) << std::endl;
        // 那么就只能释放句柄了
        mysql_close(mysql);
        return -1;
    }

    // 3. 设置客户端字符集
    // int mysql_set_character_set(mysql,"utf8")
    if (mysql_set_character_set(mysql, "utf8") != 0)
    {
        // 返回值为非0表示设置失败
        std::cout << "set character failed: " << mysql_errno(mysql) << std::endl;
        mysql_close(mysql);
        return -1;
    }

    // 4. 选择要操作的数据库
    // int mysql_select_db(mysql,dbname)
    // 当然，我们上面在连接数据库的函数中已经设置过默认要使用的数据库了，所以这里不需要操作

    // 5. 执行 sql 语句
    // int mysql_query(MYSQL* mysql,char* sql)
    // std::string sql = "insert into stu (name,age,ch,en,mt) values('张三',18,87,97,95);";
    // std::string sql = "update stu set ch=ch+1 where name='张三';";
    // std::string sql = "delete from stu where name='张三';";
    std::string sql = "select * from stu;";
    int ret = mysql_query(mysql, sql.c_str());
    if (ret != 0)
    {
        // 执行失败了
        std::cout << sql << std::endl;
        std::cout << "mysql query failed: " << mysql_errno(mysql) << std::endl;
        mysql_close(mysql);
        return -1;
    }

    // 6. 如果 sql 语句是查询语句，则需要保存结果到本地
    // MYSQL_RES* mysql_store_result(MYSQL* mysql)
    MYSQL_RES *res = mysql_store_result(mysql);
    if (res == NULL)
    {
        mysql_close(mysql);
        return -1;
    }

    // 7. 获取结果集中的结果条数
    // int mysql_num_rows(MYSQL_RES* res)——获取行数
    // int mysql_num_fields(MYSQL_RES* res)——获取列数
    int num_row = mysql_num_rows(res);   // 记录行数
    int num_col = mysql_num_fields(res); // 纪录列数

    // 8. 遍历保存到本地的结果集
    for (int i = 0; i < num_row; i++)
    {
        // MYSQL_ROW mysql_fetch_row(MYSQL_RES* res)
        MYSQL_ROW row = mysql_fetch_row(res);
        for (int j = 0; j < num_col; j++)
        {
            printf("%s\t", row[j]);
        }
        printf("\n");
    }

    // 9. 释放结果集
    mysql_free_result(res);

    // 10. 关闭连接，释放句柄
    mysql_close(mysql);

    return 0;
}